<script setup lang="ts">
import { ref, reactive, computed, getCurrentInstance, nextTick, watch } from 'vue'
import {
  searchModelByPage,
  saveModel,
  updateModel,
  revokeModel,
  selectByEntityId,
  getColumnList,
  publishModel,
  syncModel,
  resetModel,
  getDataTableList
} from '@code/api/code/model/info'
import {
  getDatasource,
} from '@code/api/newCode/scene'
import { resetFormPlus, getCustomUploadTrans, selectDictLabel, downloadUrl } from '@/utils/zmids'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
import FormModelEntityColumn from '@code/views/code/components/form-entity/column.vue'
import { cloneDeep } from 'lodash-es'
import defaultSettings from '@/settings';
import { getToken } from '@/utils/auth';

interface Form {
  modelEntityDesc: string
  modelEntityCode: string
  modelEntityFrom: string // 实体模型来源
  datasourceCode: string | undefined // 数据源code
  codeModelEntityColumnDomainList: EntityColumn[] // 实体字段列表
}

interface EntityColumn {
  modelEntityColumnName: string // 模型实体字段名称
  modelEntityColumnDesc: string // 模型实体字段描述
  dataType: string // 数据类型
  columnLength: string | number // 属性长度
  uiAdvise: string // ui建议
  defaultValue: string // 默认值
  isPrimaryKey: string // 是否主键
  isRequired: string // 是否必填
}

const loading = ref(false)

const form = ref<Form>({
  modelEntityDesc: '',
  modelEntityCode: '',
  modelEntityFrom: '',
  datasourceCode: undefined,
  codeModelEntityColumnDomainList: []
})

const formRef = ref<FormInstance>()

const queryForm = ref<FormInstance>()

const tableData = ref([])

const total = ref(0)

const title = ref('')

const type = ref('add')

const showDialog = ref<Boolean>(false)

const showSearch = ref<Boolean>(true)

const dataSourceOptions = ref([])

const dataSourceEntityName = ref('')

const queryParams = ref({
  pageNum: 1,
  pageSize: 10,
  orderBy: 'UPDATE_TIME',
  sortDirect: 'DESC',
  modelEntityCodeLike: '',
  modelEntityDescLike: ''
})

const formModelEntities = ref({
  isDeploy: 'N',
  isDetail: 'N',
  entities: [
    {
      columns: []
    }
  ]
})

const uploadRef = ref();

const upload = reactive({
  // 是否显示弹出层
  open: false,
  // 弹出层标题
  title: '',
  // 是否禁用上传
  isUploading: false,
  // 设置上传的请求头部
  headers: { [defaultSettings.tokenName]: 'Bearer ' + getToken() },
  // 上传的地址
  url: import.meta.env.VITE_APP_BASE_API + '/code/model/entity/importZip'
});

const entIndex = ref(0)

const formEntityList = ref([])

const rules = {
  modelEntityCode: [{ required: true, message: '实体编码不能为空', trigger: 'blur' }],
  modelEntityFrom: [{ required: true, message: '模型不能为空', trigger: 'change' }],
  datasourceCode: [{ required: true, message: '数据源不能为空', trigger: 'change' }],
  codeModelEntityColumnDomainList: [
    { required: true, message: '字段列表不能为空', trigger: 'blur' }
  ]
}

const modelFromOptions = [
  {
    label: '现有模型',
    value: '1'
  },
  {
    label: '空白模型',
    value: '2'
  }
]

const modelStatusOptions = [
  {
    label: '草稿',
    value: '0'
  },
  {
    label: '已发布',
    value: '1'
  },
  {
    label: '已撤销',
    value: '2'
  }
]

const getList = () => {
  return searchModelByPage(queryParams.value).then((res: any) => {
    tableData.value = res.data.list
    total.value = res.data.total
  })
}

const initForm = () => {
  resetFormPlus(formRef.value)
  form.value = {
    modelEntityDesc: '',
    modelEntityCode: '',
    modelEntityFrom: '',
    datasourceCode: undefined,
    codeModelEntityColumnDomainList: []
  }
  // 设置isDetail为N
  formModelEntities.value.isDetail = 'N'
  formModelEntities.value.entities[0].columns = []
  dataSourceEntityName.value = ''
}

const handleQuery = () => {
  queryParams.value.pageNum = 1
  getList()
}

const resetQuery = () => {
  resetFormPlus(queryForm.value)
  handleQuery()
}

const handleAdd = () => {
  initForm()
  showDialog.value = true
  title.value = '新增实体'
  type.value = 'add'
}

const handleUpdate = (row: any) => {
  selectByEntityId(row.modelEntityId).then((response) => {
    const { modelEntityStatus, modelEntityFrom } = row
    form.value = response.data

    if (form.value.codeModelEntityColumnDomainList) {
      if (modelEntityStatus == '0' && modelEntityFrom == '2') {
        formModelEntities.value.entities[0].columns = cloneDeep(
          form.value.codeModelEntityColumnDomainList
        )
      } else {
        formModelEntities.value.entities[0].columns = cloneDeep(
          form.value.codeModelEntityColumnDomainList
        ).map((item) => {
          item.isAllowEdit = 'N'
          return item
        })
      }
    }
    dataSourceEntityName.value = form.value.modelEntityCode
    type.value = 'update'
    title.value = '修改实体'
    showDialog.value = true
  })
}

const handleDetails = (row: any) => {
  selectByEntityId(row.modelEntityId).then((response) => {
    form.value = response.data

    // 对每一行新增属性 isAllowEdit='N' 即详情禁止修改
    form.value.codeModelEntityColumnDomainList = form.value.codeModelEntityColumnDomainList.map(
      (item) => {
        item.isAllowEdit = 'N'
        return item
      }
    )

    // 设置isDetail为Y
    formModelEntities.value.isDetail = 'Y'

    if (form.value.codeModelEntityColumnDomainList) {
      formModelEntities.value.entities[0].columns = cloneDeep(
        form.value.codeModelEntityColumnDomainList
      )
    }
    dataSourceEntityName.value = form.value.modelEntityCode
    getModelColumn()
    type.value = 'detail'
    title.value = '实体详情'
    showDialog.value = true
  })
}

const handleDelete = (row: any) => {
  const params = {
    ...row,
    isDelete: 'Y'
  }
  updateModel(params)
    .then((res) => {
      ElMessage.success('删除成功')
      getList()
    })
    .catch(function () {})
}

const handleApply = (row: any) => {
  return publishModel(row.modelEntityId).then((res) => {
    if (res.code == '200') {
      ElMessage.success('发布成功')
      getList()
    } else {
      ElMessage.error('发布失败')
    }
  })
}

const handleRevoke = (row: any) => {
  return revokeModel(row.modelEntityId).then((res) => {
    if (res.code == '200') {
      ElMessage.success('撤销成功')
      getList()
    } else {
      ElMessage.error('撤销失败')
    }
  })
}

const handleSync = (row: any) => {
  return syncModel(row.modelEntityId).then((res) => {
    if (res.code == '200') {
      ElMessage.success('同步成功')
      getList()
    } else {
      ElMessage.error('同步失败')
    }
  })
}

const handleExport = (row: any) => {
  downloadUrl('/code/model/entity/exportZip/' + row.modelEntityCode, undefined)
}

const handleImport = () => {
  upload.title = '模型管理迁入';
  upload.open = true;
}

// 上传中回调
const handleFileUploadProgress = () => {
  upload.isUploading = true;
}

// 上传完成后回调
const handleFileSuccess = (response, file, fileList) => {
  cancelUpload();
  ElMessageBox.alert(response.msg, '迁入结果', { dangerouslyUseHTMLString: true });
  getList();
}

// 提交上传
const submitFileForm = () => {
  uploadRef.value.submit();
};

// 取消上传
const cancelUpload = () => {
  upload.open = false;
  upload.isUploading = false;
  uploadRef.value.clearFiles();
};

const handleReset = (row: any) => {
  return resetModel(row.modelEntityId).then((res) => {
    if (res.code == '200') {
      ElMessage.success('重置成功')
      getList()
    } else {
      ElMessage.error('重置失败')
    }
  })
}

const submitForm = (formEl: FormInstance | undefined) => {
  if (!formEl) {
    return
  }
  formEl.validate((valid) => {
    if (valid) {
      const entityColumn = form.value.codeModelEntityColumnDomainList.map(item => item.modelEntityColumnName)
      const uniqueSet = new Set(entityColumn);
      if (uniqueSet.size !== entityColumn.length){
        ElMessage.error('字段名称有重复值，请检查！')
        return
      }
      if (type.value == 'update') {
        updateModel(form.value).then((response) => {
          if (response.code === '200') {
            ElMessage.success('修改成功')
            showDialog.value = false
            getList()
          }
        })
      } else {
        saveModel(form.value).then((response) => {
          if (response.code === '200') {
            ElMessage.success('新增成功')
            showDialog.value = false
            getList()
          }
        })
      }
    }
  })
}

const cancel = () => {
  // 设置isDetail为N
  formModelEntities.value.isDetail = 'N'
  showDialog.value = false
  initForm()
}

const getOptItem = (value: string, options: any[]) => {
  return options.find((opt) => opt.value == value)
}

const getDataSourceOptions = () => {
  return getDatasource().then((res) => {
    dataSourceOptions.value = res.data
  })
}

// 选中时触发
const handleSelectBranchCom = (value: string, index: number, type: string) => {
  form.value.modelEntityCode = value
  formModelEntities.value.entities[index]['isExternal'] = 'Y'
  // this.$set(this.formData.entities[index],'isExternal', 'Y' ) //选择现有模型时候才会传Y
  let fe = formEntityList.value.filter((item) => {
    return item.dictValue == value
  })
  formModelEntities.value.entities[index]['formEntityDesc'] = fe[0].dictLabel
  // this.$set(this.formData.entities[index],'formEntityDesc', fe[0].dictLabel )
  if (type == 'T1') {
    formModelEntities.value.entities[index]['formEntityName'] = value
    // this.$set(this.formData.entities[index],'formEntityName', value )
  } else if (type == 'T2') {
    formModelEntities.value.entities[index]['formEntityDescId'] = value
    // this.$set(this.formData.entities[index],'formEntityDescId', value )
  }
  getDataColumnAttr(index)
}

// 获取实体
const getModelColumn = () => {
  if (form.value.datasourceCode != undefined) {
    getDataTableList(form.value.datasourceCode).then((res) => {
      formEntityList.value = res.data
    })
  }
}

const getDataColumnAttr = (index: number) => {
  let totalEntIndex = index + 1
  const params = {
    datasourceCode: form.value.datasourceCode,
    tableName: dataSourceEntityName.value
  }
  getColumnList(params).then((res) => {
    res.data.forEach((item) => {
      item.index = totalEntIndex
    })
    formModelEntities.value.entities[index]['updStatus'] = 'ADD'
    formModelEntities.value.entities[index].columns = cloneDeep(res.data).map((item) => {
      item.isAllowEdit = 'N'
      return item
    })
    // this.$set(this.formData.entities[index],'updStatus', 'ADD')
    // this.$set(this.formData.entities[index],'columns', res.data.entities.columns)
    // this.$emit('getFormModelEntities', this.formDataEnts.entities)
  })
}

const chineseFormat = () => {}

const attrNameFormat = () => {}

watch(
  formModelEntities,
  (value: any) => {
    form.value.codeModelEntityColumnDomainList = cloneDeep(value.entities[0].columns)
  },
  {
    deep: true
  }
)

const init = () => {
  getList()
  getDataSourceOptions()
}

init()
</script>

<template>
  <div class="app-container">
    <el-form
      :model="queryParams"
      ref="queryForm"
      :inline="true"
      v-show="showSearch"
      label-width="68px"
    >
      <el-form-item label="实体编码" prop="modelEntityCodeLike">
        <el-input
          v-model="queryParams.modelEntityCodeLike"
          placeholder="请输入实体编码"
          clearable
          size="default"
          style="width: 240px"
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="实体描述" prop="modelEntityDescLike">
        <el-input
          v-model="queryParams.modelEntityDescLike"
          placeholder="请输入实体描述"
          clearable
          size="default"
          style="width: 240px"
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <search-button @click="handleQuery" />
        <reset-button @click="resetQuery" />
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <add-button @click="handleAdd" />
      <import-button @click="handleImport" text="迁入" />
      <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
    </el-row>

    <el-table v-loading="loading" :data="tableData">
      <el-table-column label="实体编码" align="center" prop="modelEntityCode" width="200" />
      <el-table-column label="实体描述" align="center" prop="modelEntityDesc" width="200" />
      <el-table-column label="实体来源" align="center" prop="modelEntityFrom" width="150">
        <template #default="scope">
          {{ getOptItem(scope.row.modelEntityFrom, modelFromOptions).label }}
        </template>
      </el-table-column>
      <el-table-column label="所属数据源" align="center" prop="datasourceCode" width="200" />
      <el-table-column label="实体状态" align="center" prop="modelEntityStatus" width="150">
        <template #default="scope">
          {{ getOptItem(scope.row.modelEntityStatus, modelStatusOptions).label }}
        </template>
      </el-table-column>
      <el-table-column label="更新者" align="center" prop="updateBy" width="100" />
      <el-table-column label="更新时间" align="center" prop="updateTime" min-width="300" />
      <el-table-column
        label="操作"
        align="center"
        class-name="small-padding fixed-width"
        width="300"
      >
        <template #default="scope">
          <text-download-button
            @click="handleExport(scope.row)"
            text="迁出"
          />
          <text-reset-button
            @click="handleReset(scope.row)"
            v-if="scope.row.modelEntityStatus == '2'"
          />
          <text-edit-button
            @click="handleUpdate(scope.row)"
            v-if="scope.row.modelEntityStatus !== '1'"
          />
          <text-detail-button @click="handleDetails(scope.row)" text="详细" />
          <text-add-button
            @click="handleApply(scope.row)"
            text="发布"
            v-if="scope.row.modelEntityStatus !== '1'"
          />
          <text-button
            @click="handleRevoke(scope.row)"
            v-if="scope.row.modelEntityStatus == '1'"
            icon="el-icon-back"
            text="撤销"
          />
          <text-button
            @click="handleSync(scope.row)"
            v-if="scope.row.modelEntityFrom == '1' || (scope.row.modelEntityFrom == '2' && scope.row.modelEntityStatus == '1')"
            icon="el-icon-refresh"
            text="同步"
          />
          <text-delete-button
            @click="handleDelete(scope.row)"
            :title="'是否确认删除' + scope.row.modelEntityCode + '?'"
          />
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total > 0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <drag-dialog
      v-el-drag-dialog
      :title="title"
      :close-on-click-modal="false"
      v-model="showDialog"
      width="1200px"
      fullscreen
      append-to-body
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
        <el-form-item label="实体名称" prop="modelEntityDesc">
          <el-input
            v-model="form.modelEntityDesc"
            placeholder="请输入实体名称"
            :disabled="type == 'detail'"
          />
        </el-form-item>
        <el-form-item label="实体编码" prop="modelEntityCode">
          <el-input
            v-model="form.modelEntityCode"
            placeholder="请输入实体编码"
            :disabled="type == 'update' || type == 'detail'"
          />
        </el-form-item>
        <el-form-item label="模型来源" prop="modelEntityFrom">
          <el-select
            v-model="form.modelEntityFrom"
            placeholder="请选择模型来源"
            :disabled="type == 'update' || type == 'detail'"
            filterable
            clearable
          >
            <el-option
              v-for="(opt, idx) in modelFromOptions"
              :key="idx"
              :label="opt.label"
              :value="opt.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="数据源" prop="datasourceCode">
          <el-select
            v-model="form.datasourceCode"
            placeholder="请选择数据源"
            @change="getModelColumn"
            :disabled="type == 'update' || type == 'detail'"
            filterable
            clearable
          >
            <el-option
              v-for="(op, index) in dataSourceOptions"
              :key="index"
              :label="op.datasourceName"
              :value="op.datasourceCode"
            />
          </el-select>
        </el-form-item>
        <el-form-item
          label="数据源实体"
          v-if="form.modelEntityFrom == '1' && form.datasourceCode"
          required
        >
          <el-select
            v-model="dataSourceEntityName"
            placeholder="请选择数据源实体"
            @change="
              (value) => {
                handleSelectBranchCom(value, 0, 'T2')
              }
            "
            :disabled="type == 'update'"
            filterable
            clearable
          >
            <el-option
              v-for="(opt, ind) in formEntityList"
              :key="ind"
              :label="opt.dictValue"
              :value="opt.dictValue"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="实体字段列表" prop="codeModelEntityColumnDomainList">
          <form-model-entity-column
            v-model:data="formModelEntities"
            :entIndex="entIndex"
            @chinese-format="chineseFormat"
            @attr-name-format="attrNameFormat"
            @ent-blur="entBlur"
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="submitForm(formRef)" :disabled="type == 'detail'"
          >保 存</el-button
          >
          <el-button @click="cancel">取 消</el-button>
        </span>
      </template>
    </drag-dialog>

    <drag-dialog :title="upload.title" :close-on-click-modal="false" v-model="upload.open" width="400px" append-to-body>
      <el-upload
        ref="uploadRef"
        :limit="1"
        accept=".zip"
        :headers="upload.headers"
        :action="upload.url"
        :disabled="upload.isUploading"
        :on-progress="handleFileUploadProgress"
        :on-success="handleFileSuccess"
        :auto-upload="false"
        drag
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">
          将文件拖到此处，或
          <em>点击上传</em>
        </div>
        <template #tip>
          <div class="el-upload__tip">
            Tips：迁入迁出主要用于多环境间数据传递，因此不建议用户对迁出的包进行修改
            <div class="el-upload__tip" style="color: red"> 提示：仅允许上传“zip”格式文件！ </div>
          </div>
        </template>
      </el-upload>
      <template #footer>
        <dialog-footer @ok="submitFileForm" @cancel="cancelUpload" />
      </template>
    </drag-dialog>
  </div>
</template>

<style lang="scss">
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}

.avatar-uploader-icon {
  font-size: 28px !important;
  color: #8c939d !important;
  width: 178px !important;
  height: 178px !important;
  line-height: 178px !important;
  text-align: center !important;
}

.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>
